<!--
 * @Date: 2024-12-19 10:42:24
 * @Author: LiSong
 * @LastEditors: LiSong
 * @LastEditTime: 2025-02-24 09:27:27
 * @Description: 主页设计抽屉
-->
<template>
  <el-drawer ref="drawerRef" :="drawerAttrs" v-model="drawerState.visible">
    <div class="hp-design-drawer-wrapper">
      <div class="design-drawer-head">
        <div class="header-title">
          {{ formState.baseInfo.name }}
        </div>
        <div class="header-steps">
          <el-steps simple :active="stepState.stepActive" finish-status="success" >
						<el-step title="基本配置" />
						<el-step title="主页设计" />
						<el-step title="主页预览" />
					</el-steps>
        </div>
        <div class="header-tools">
          <el-button @click="handlePrevStep()" :disabled="stepState.stepActive <= stepState.ksStep">上一步</el-button>
          <el-button @click="handleNextStep()" :disabled="stepState.stepActive >= stepState.jsStep">下一步</el-button>
          <el-button type="primary" :disabled="saveDisable" @click="handleSave">保存</el-button>
          <el-button type="danger" @click="handleClose">关闭</el-button>
        </div>
      </div>
      <div class="design-drawer-body">
        <template v-if="stepState.stepActive === 0" >
          <div class="base-info-panel">
            <el-form
              ref="baseFormRef"
              :="baseFormAttrs"
              :model="formState.baseInfo"
              :rules="baseFormRules"
            >
              <el-form-item label="名称" prop="name">
                <el-input v-model="formState.baseInfo.name" />
              </el-form-item>
              <el-form-item label="编码" prop="code">
                <el-input v-model="formState.baseInfo.code" />
              </el-form-item>
              <el-form-item label="类型" prop="formTypeName">
                <el-input readonly v-model="formState.baseInfo.formTypeName" />
              </el-form-item>
              <el-form-item label="排序" prop="orderNum">
                <el-input-number style="width: 100%;" v-model="formState.baseInfo.orderNum" />
              </el-form-item>
              <el-form-item label="描述" prop="remark">
                <el-input v-model="formState.baseInfo.remark" type="textarea" :autosize="{ minRows: 10, maxRows: 12 }" />
              </el-form-item>
            </el-form>
          </div>
        </template>
        <template v-if="stepState.stepActive === 1" >
          <HpDesigner
            ref="hpDesignRef"
            :layouts="formState.designInfo"
          />
        </template>
        <template v-if="stepState.stepActive === 2" >
          <HpRender
            ref="hpRenderRef"
            id="cupture-area"
            :layouts="formState.designInfo"
            :design="true"
          />
        </template>
      </div>
    </div>
  </el-drawer>
</template>

<script setup>
import { defAxios } from '@/utils/http';
import { reactive, ref } from 'vue';
import { getUUID } from '@hp/utils/data';
import { ElLoading, ElMessage, ElMessageBox } from 'element-plus';

import html2canvas from 'html2canvas';
import { HpDesigner, HpRender } from '@hp'

const emits = defineEmits(['success'])

// 抽屉组件的Ref
const drawerRef = ref()
//
const hpRenderRef = ref()
// 主页设计组件的Ref
const hpDesignRef = ref()

// 默认数据
const defInfo = {
  // 表单编码
  code: '',
  // 表单名称
  name: '',
  // 0-未启用 1-已启用
  status: 0,
  // 表单备注
  remark: '',
  // 唯一ID
  formId: '',
  // 表单类型
  formType: '',
  // 排序
  orderNum: 1,
  // 图片路径
  imageStr: '',
  // 表单的种类 1-表单 2-主页
  category: '2',
  // 提交请求地址
  submitURL: '',
  // 表单类型名称
  formTypeName: '',
  // 校验规则
  validateContent: ''
}
// 表单数据集
const formState = reactive({
  baseInfo: JSON.parse(JSON.stringify(defInfo)),
  designInfo: []
})
// 抽屉的数据集
const drawerState = reactive({
  mode: 'add',
  visible: false,
})
// 抽屉组件的属性定义
const drawerAttrs = reactive({
  size: '100%',
  class: 'hp-design-drawer',
  zIndex: 2000,
  showClose: false,
  withHeader: false,
  appendToBody: true,
  closeOnPressEscape: false,
})

/**
 * 新增操作
 */
const handleAdd = async (info={}) => {
  drawerState.visible = true
  // 设置模式
  drawerState.mode = 'add'
  // 合并基本信息
  mergeBaseData(info)
}
/**
 * 编辑操作
 */
const handleEdit = async (info) => {
  drawerState.visible = true
  // 设置模式
  drawerState.mode = 'edit'
  const loadService = ElLoading.service({ fullscreen: true, text: '加载中......' })
  // 获取设计信息
  const data = await reqGetDesignInfo(info?.formId)
  formState.designInfo = data.formJson
  // 合并基本信息
  mergeBaseData({ ...data.baseInfo }, info)
  loadService.close()
}
/**
 * 保存数据
 */
const handleSave = async () => {
  if (stepState.stepActive === 1) {
    let flag = await setDesignData()
    if (!flag) return
  }

  // 封装数据
  const prdFormContent = {
    slotJson: '',
    submitURL: '',
    structureJson: JSON.stringify(formState.designInfo),
    validateContent: '',
  }
  
  // 设置截图
  const canvasEl = hpRenderRef.value.$el
  const screenshot = await getScreenshot(canvasEl)
  formState.baseInfo.imageStr = screenshot.imgBase64

  // 提交数据
  const submitDesignData = {
    ...formState.baseInfo,
    prdFormContent,
    prdFormFieldBo: []
  }
  // const submitDesignData = submitData
  // console.log('submitDesignData', submitDesignData)
  // return
  const loadService = ElLoading.service({ fullscreen: true, text: '保存中......' })
  const flag = await reqSaveDesignInfo(submitDesignData)
  loadService.close()
  if (!flag) return
  emits('success', submitDesignData)
  if (stepState.stepActive <= 1) return
  handleReset()
  drawerState.visible = false
}
/**
 * 重置数据
 */
const handleReset = () => {
  // 重置表单校验
  if (baseFormRef.value) baseFormRef.value.resetFields()
  formState.baseInfo = JSON.parse(JSON.stringify(defInfo))
  formState.designInfo = []
  stepState.stepActive = stepState.ksStep
}
/**
 * 关闭抽屉
 */
const handleClose = () => {
  ElMessageBox.confirm(
    '关闭后所有未保存的数据将会清空，请谨慎操作！',
    '提示',
    {
      type: 'warning',
      showClose: false,
      customStyle: {
        'margin-top': '120px',
        'vertical-align': 'top',
      },
      closeOnClickModal: true
    }
  ).then(() => {
    drawerState.visible = false
    handleReset()
  }).catch(() => {
  })
}

// 步骤条组件的数据集
const stepState = reactive({
  ksStep: 0,
  jsStep: 2,
  stepActive: 0,
})
// 保存按钮是否禁用
const saveDisable = computed(() => {
  return !(stepState.stepActive >= 2)
  // if (drawerState.mode === 'add') {
  //   return !(stepState.stepActive >= 2)
  // } else {
  //   return !(stepState.stepActive >= 0)
  // }
})
/**
 * 上一步操作
 */
const handlePrevStep = () => {
  if (stepState.stepActive-- < 1) stepState.stepActive = stepState.ksStep;
}
/**
 * 下一步操作
 */
const handleNextStep = async () => {
  let nextGo = false
  switch (stepState.stepActive) {
    case 0:
      nextGo = await validateBaseForm()
      break;
    case 1:
      nextGo = await setDesignData()
      break;
    case 2:
      break;
    default:
      break;
  }
  if (!nextGo) return
  if (stepState.stepActive++ > stepState.jsStep) stepState.stepActive = stepState.ksStep;
}

// 表单组件的Ref
const baseFormRef = ref(null)
// 表单组件的属性定义
const baseFormAttrs = reactive({
  labelWidth: 'auto'
})
// 表单字段校验规则
const baseFormRules = reactive({
  name: [
    { required: true, message: '请输入名称', trigger: 'blur' }
  ],
  code: [
    { required: true, message: '请输入编码', trigger: 'blur' }
  ],
  // formType: [
  //   { required: true, message: '请输入类型', trigger: 'blur' }
  // ],
  orderNum: [
    { required: false, message: '请输入排序', trigger: 'blur' }
  ],
})
/**
 * 校验基础信息表单
 */
const validateBaseForm = async () => {
  return new Promise((resolve, reject) => {
    baseFormRef.value.validate((valid) => {
      if (valid) {
        resolve(true)
      } else {
        resolve(false)
      }
    })
  })
}

/**
 * 合并基本信息
 * @param {Object} data 需要合并的数据
 */
const mergeBaseData = (data, row={}) => {
  Object.keys(defInfo).forEach(key => {
    formState.baseInfo[key] = data[key] || row[key] || defInfo[key]
  })
}
/**
 * 设置设计数据
 */
const setDesignData = async () => {
  const designRef = hpDesignRef.value
  // 获取设计数据
  const designData = designRef.getDesignData()
  if (!designData || (designData && designData.length === 0)) {
    ElMessage.warning('请先设计主页')
    return false
  }
  formState.designInfo = designData
  return true
}
/**
 * 截图方法
 * 
 * @param el 需要截图的DOM
 */
const getScreenshot = (el) => {
  return new Promise((resolve, reject) => {
    let options = {
      scale: 0.35,
      width: el.offsetWidth,
      height: el.offsetHeight,
      useCORS: true, // 是否尝试使用 CORS 从服务器加载图像
      allowTaint: false, // 是否允许跨源图像污染画布
    }
    const result = {
      imgBase64: '', imgBlobUrl: '',
    }
    html2canvas(el, options).then((canvas) => {
      // 转base64
      result.imgBase64 = canvas.toDataURL("image/jpeg");
      // 转blobUrl
      canvas.toBlob((blob) => {
        result.imgBlobUrl = URL.createObjectURL(blob)
        resolve(result)
      })
    });
  })
  
}


// 抽屉中请求API
const drawerApis = {
  /**
   * 根据表达ID获取表单信息
   * 
   * @param formId 表单ID
   */
  reqGetDesignData: (formId) => {
    return defAxios({
      url: '/prdFormInfo/queryPrdFormInfoListByFormId',
      method: 'GET',
      params: { formId }
    })
  },
  /**
   * 保存表单信息
   */
  reqSaveDesignData: (params) => {
    return defAxios({
      url: '/prdFormInfo/addPrdFormInfo',
      method: 'POST',
      data: params,
    });
  },
}
const reqGetDesignInfo = (id) => {
  return new Promise((resolve) => {
    // const result = {
    //   baseInfo: {
    //     name: '角色主页',
    //     code: 'hp-role-home',
    //     formId: getUUID(),
    //     formType: '1',
    //     orderNum: 1,
    //     remark: '',
    //   },
    //   slotJson: [],
    //   formJson: JSON.parse('[{"i":"e008949508d8459f8ef2eea9f6dc4e0f","x":0,"y":0,"w":24,"h":12,"minW":24,"minH":12,"maxW":60,"maxH":24,"static":false,"type":"databoard","name":"数据面板1","schema":{"label":"数据面板1","desc":"","iconType":"img","dataKeys":{"v1":"","v2":""},"dataSource":{"type":"static","sqlConfig":{"content":"","responseFunc":""},"viewConfig":{"dataType":"view","dataCode":"","dataParams":"","responseFunc":""},"serverConfig":{"url":"","method":"POST","params":"","paramsType":"data","responseFunc":""},"staticConfig":{"dataValue":""}},"id":"e008949508d8459f8ef2eea9f6dc4e0f"},"moved":false},{"i":"64a7197a0460461da3bfeec5f4a018ae","x":24,"y":0,"w":24,"h":12,"minW":24,"minH":12,"maxW":120,"maxH":24,"static":false,"type":"databoard2","name":"数据面板2","schema":{"label":"数据面板2","desc":"","dataKeys":{"v1":""},"dataSource":{"type":"static","sqlConfig":{"content":"","responseFunc":""},"viewConfig":{"dataType":"view","dataCode":"","dataParams":"","responseFunc":""},"serverConfig":{"url":"","method":"POST","params":"","paramsType":"data","responseFunc":""},"staticConfig":{"dataValue":""}},"id":"64a7197a0460461da3bfeec5f4a018ae"},"moved":false},{"i":"ce3ed7eef0714c099448302fad96f09a","x":48,"y":0,"w":36,"h":16,"minW":24,"minH":12,"maxW":120,"maxH":24,"static":false,"type":"databoard3","name":"数据面板3","schema":{"desc":"","label":"数据面板3","label1":"","label2":"","dataKeys":{"v1":"","v2":""},"dataSource":"","id":"ce3ed7eef0714c099448302fad96f09a"},"moved":false},{"i":"9237cdc6ca864358a317da0c8a21e021","x":84,"y":0,"w":36,"h":16,"minW":24,"minH":12,"maxW":120,"maxH":24,"static":false,"type":"databoard3","name":"数据面板3","schema":{"desc":"","label":"数据面板3","label1":"","label2":"","dataKeys":{"v1":"","v2":""},"dataSource":"","id":"9237cdc6ca864358a317da0c8a21e021"},"moved":false}]')
    // }
    // resolve(result);
    const result = {
      baseInfo: {},
      slotJson: [],
      formJson: []
    }
    drawerApis.reqGetDesignData(id).then(res => {
      if (res.code === 200) {
        const { data } = res
        const { prdFormContent } = data
        if (prdFormContent && prdFormContent.structureJson) {
          try {
            result.formJson = JSON.parse(prdFormContent.structureJson)
            result.slotJson = JSON.parse(prdFormContent.slotJson)
            result.baseInfo = { ...data, ...prdFormContent }
          } catch (error) {
            console.error('解析表单数据失败', error)
          }
        }
        resolve(result)
      } else {
        resolve(result);
        console.error(res.msg)
      }
    }).catch(err => {
      resolve(result);
      console.error('获取配置数据失败', err)
    })
  })
}
const reqSaveDesignInfo = (params) => {
  return new Promise((resolve, reject) => {
    // const res = { code: 200, msg: '保存成功', data: {} }
    // if (res.code === 200) {
    //   ElMessage.success('保存成功！')
    //   resolve(true)
    // } else {
    //   ElMessage.success('保存失败！')
    //   resolve(false)
    // }
    drawerApis.reqSaveDesignData(params).then(res => {
      if (res.code === 200) {
        ElMessage.success('保存成功！')
        resolve(true)
      } else {
        ElMessage.error(res.msg);
        resolve(false)
      }
    }).catch(error => {
      console.error(error);
      resolve(false)
    }) 
  })
}

defineExpose({
  handleAdd,
  handleEdit,
})

</script>

<style lang="scss" scoped>
.hp-design-drawer {
  &-wrapper {
    height: 100%;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
  }
}
.design-drawer-head {
  display: flex;
  width: 100%;
  padding: 0 8px;
  height: 50px;
  line-height: 50px;
  align-items: center;
  border-bottom: 1px solid #d9d9d9;
  background-color: #fff;
  .header-title {
    width: 300px;
    font-size: 16px;
  }
  .header-steps {
    flex: 1;
    line-height: 1;
    padding: 15px 120px 15px 30px;
    .el-steps {
			padding: 0;
			background-color: #fff;
		}
  }
  .header-tools {
    // width: 330px;
    text-align: right;
  }
}
.design-drawer-body {
  flex: 1;
  min-height: 100px;
}
.base-info-panel {
  width: 60%;
  margin: 0 auto;
  margin-top: 30px;
}
:deep(.el-step.is-simple .el-step__icon) {
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
}
:deep(.el-step__icon-inner) {
  font-size: 24px !important;
}
</style>
